package com.zone.builder.xml;

import cn.hutool.core.convert.Convert;
import com.zone.builder.xml.base.BaseBuild;
import com.zone.io.Resources;
import com.zone.mapping.MappedStatement;
import com.zone.mapping.SqlCommonType;
import com.zone.session.Configuration;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;

import java.io.Reader;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author: zongzi
 * @description: TODO
 * @date: 2023/12/4
 */
public class XmlConfigBuild extends BaseBuild {

    public XmlConfigBuild() {
        super(new Configuration());
    }

    public Configuration parse(Reader reader) throws DocumentException {
        SAXReader saxReader = new SAXReader();
        Document document = saxReader.read(reader);

        parseConfiguration(document.selectSingleNode("/configuration"));
        return configuration;
    }

    private void parseConfiguration(Node root) {
        try {
            mapperElement(root.selectSingleNode("/configuration/mappers"));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private void mapperElement(Node mappers) throws Exception {
        List<Node> mapperNodes = mappers.selectNodes("/configuration/mappers/mapper");
        List<Element> elements = Convert.toList(Element.class, mapperNodes);

        for (Element element : elements) {
            String resource = element.attributeValue("resource");

            // 解析user_mapper.xml
            Reader reader = Resources.getReaderByResourcePath(resource);
            SAXReader saxReader = new SAXReader();
            Document mapperXml = saxReader.read(reader);
            Element root = mapperXml.getRootElement();
            String namespace = root.attributeValue("namespace");

            List<Element> selectList = root.elements("select");
            for (Element selectElement : selectList) {
                String id = selectElement.attributeValue("id");
                String parameterType = selectElement.attributeValue("parameterType");
                String resultType = selectElement.attributeValue("resultType");
                SqlCommonType sqlCommonType = SqlCommonType.valueOf(selectElement.getName().toUpperCase(Locale.ENGLISH));

                // 将sql中的占位符用?替代
                String sql = selectElement.getText();
                Pattern pattern = Pattern.compile("(#\\{(.*?)})");
                Matcher matcher = pattern.matcher(sql);
                Map<Integer, String> params = new HashMap<>();
                for (int i = 1; matcher.find(); i++) {
                    // #{xxx}
                    String g1 = matcher.group(1);
                    // xxx
                    String g2 = matcher.group(2);
                    params.put(i, g2);
                    sql = sql.replace(g1, "?");
                }


                MappedStatement mappedStatement = new MappedStatement(sqlCommonType, namespace, id, parameterType, resultType, sql, params);
                this.configuration.addStatement(mappedStatement);
            }

            configuration.addMapper(Resources.classForName(namespace));
        }
    }
}
